/*
    This is a set of libraries to assist in OpenGl and Other Applications
    Copyright (C) 2008  The Modular Engine Team

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REGISTRYMODULE_H
#define REGISTRYMODULE_H
#include "EngineCore.h"
#include "ConsoleModule.h"
#include "math.h"
#include <fstream>
#include <list>
#include <sstream>
#include <string>


#undef CLASSDECL
#ifdef REGISTRYMODULE
	#define CLASSDECL __declspec(dllexport)
#else
	#pragma comment( lib, "RegistryModule.lib" )
	#define CLASSDECL __declspec(dllimport)
#endif

// Tired of typing std::
// may remove later, but there "should" be no conflicts
using namespace std;

namespace ModularEngine
{
	CFUNCTOR( cSAVEREGISTRY, "saveregistry" );
	CFUNCTOR( cLOADREGISTRY, "loadregistry" );
	CFUNCTOR( cSET, "set" );

	class CLASSDECL RegistryKey
	{
	public:
		bool mbSaveable; // By default, all keys are saveable
		// but some are stupid to save.
		bool bInUse; // Is the key still in use.  If so, don't delete it.
		char *mKeyName; // The name of the registry key
		char *mKeyValue; // the value of the key
		int mValSize; // size in characters of the value

		RegistryKey()
		{
			
			mbSaveable = true;
			bInUse = true;
			mKeyName = 0;
			mKeyValue = 0;
			mValSize = 0;
			
		}

		~RegistryKey()
		{
			if( !bInUse )
			{
				if( mKeyName )
					delete [] mKeyName;
				if( mKeyValue )
					delete [] mKeyValue;
				mKeyName = 0;
				mKeyValue = 0;
			}
		}

		void setName( const char *pName )
		{
			// If we're changing the name, remove the original
			if( mKeyName )
			{
				delete [] mKeyName;
			}
			// Set the key
			mKeyName = new char[strlen(pName)+1];
			strcpy( mKeyName, pName );			
		}

		void setOther( void *pValue, int size )
		{
			// Set a value other than a number or string to the key.
			mKeyValue = new char[size];
			// Copy the key to the value, with a size of size
			memcpy( mKeyValue, pValue, size );
			mValSize = size;
		}

		void operator = (double nValue)
		{
			if( mKeyValue )
				delete [] mKeyValue;
			mKeyValue = new char[32];
			// Convert the value to a number and save it in the value
			sprintf( mKeyValue, "%Lf\0", nValue );
			// mValSize set to the end of the string \0
			mValSize = strlen(mKeyValue)+1;
		}

		void operator = (const char *pValue)
		{
			if( mKeyValue )
			{
				delete [] mKeyValue;
			}
			mValSize = strlen(pValue)+1;
			mKeyValue = new char[mValSize];
			strcpy( mKeyValue, pValue);
		}

		bool operator == (void *pValue)
		{
			if( (void *)mKeyValue == pValue )
				return true;
			return false;
		}

		bool operator == (double nValue)
		{
			if( !this )
				return false;

			if( mKeyValue == 0 )
				return false;
			// Check numeric value of the Key 
			if( atof( mKeyValue ) == nValue )
				return true;
			return false;
		}

		bool operator == (const char *pValue)
		{
			if( !strcmp( pValue, mKeyValue ) )
				return true;
			return false;
		}

		const char *operator () ()
		{
			return mKeyValue;
		}

		

	};

	class CLASSDECL RegistryModule: BASE( RegistryModule )
	{
	public:

		// List of the Registry Keys
		list<RegistryKey> mKeys;

		// The various ways to set values
		void setValue( const char *keyName, void *pValue, int size );
		void setValue( const char *keyName, double nValue );
		void setValue( const char *keyName, const char *pValue );

		// Return reference to RegistryKey with that name
		RegistryKey &getKey( const char *keyName );
		
		// does the key exist in the registry
		bool doesExist( const char *keyName );

		// Load/Save Registry to a File
		int loadRegistry( const char *path );
		int saveRegistry( const char *path );

		int initialize();
		int run();

	};
}

#endif